package com.xianniu.ltc.service.impl;

import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.Query;
import cn.devezhao.persist4j.engine.ID;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rebuild.core.Application;
import com.rebuild.core.UserContextHolder;
import com.rebuild.core.configuration.general.ClassificationManager;
import com.rebuild.core.metadata.EntityHelper;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.privileges.DepartmentService;
import com.rebuild.core.privileges.UserService;
import com.rebuild.core.privileges.bizz.User;
import com.rebuild.core.service.dataimport.DataExporter;
import com.xianniu.ltc.common.Constant;
import com.xianniu.ltc.enums.*;
import com.xianniu.ltc.mapper.*;
import com.xianniu.ltc.model.entity.*;
import com.xianniu.ltc.model.po.*;
import com.xianniu.ltc.model.po.imports.ImportLeadPO;
import com.xianniu.ltc.model.vo.XnLeadVO;
import com.xianniu.ltc.service.XnLeadService;
import com.xxl.sso.core.entity.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author WangRuiJie
 * @Title: XnLeadServiceImpl
 * @Package com.xianniu.ltc.service.impl
 * @Description:
 * @date 2021/6/911:24 上午
 */
@Slf4j
@Service
public class XnLeadServiceImpl implements XnLeadService {

    @Resource
    private TXnLeadMapper leadMapper;
    @Resource
    private TXnLeadTeamMapper leadTeamMapper;
    @Resource
    private TUserMapper userMapper;
    @Resource
    private TDepartmentMapper departmentMapper;
    @Resource
    private TXnLimitRuleMapper ruleMapper;
    @Resource
    private TXnLeadRecordMapper recordMapper;
    @Resource
    private TSihaixiansuoMapper sihaixiansuoMapper;
    @Resource
    private TGonghaixiansuoMapper gonghaixiansuoMapper;
    @Resource
    private TMetaFieldMapper metaFieldMapper;


    @Override
    public IPage<XnLeadVO> selectLeadForAdmin(QueryLeadAdminPO po) {
        String tenantCode = UserContextHolder.getTenant();
        Page<TXnLeadDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        IPage<XnLeadVO> dtoList = leadMapper.selectPageList(page, po, Constant.INT_0, tenantCode);
        return dtoList;
    }

    @Override
    public XnLeadVO detailLeadForAdmin(String id) {
        String entityName = MetadataHelper.getEntityName(ID.valueOf(id));
        XnLeadVO vo = new XnLeadVO();
        // 私海线索
        if (entityName.equalsIgnoreCase("sihaixiansuo")){
            leadMapper.detailPLeadForAdmin(id);
        }else {
            // 公海线索
            leadMapper.detailCLeadForAdmin(id);
        }
        return vo;
    }

    /**
     * 后台:线索管理转移分组：
     *  校验已领取的不能转移：588为私海线索，私海线索不能转移
     * @param po
     * @return
     */
    @Override
    public ReturnT transferLeadForAdmin(TransferLeadPO po) {
        Boolean flag =false;
        for (String leadId:po.getLeadIdList()){
            if (leadId.contains(EntityHelper.SiHaiXianSuo+"")){
                flag = true;
            }
        }
        if (flag){
            return new ReturnT(400, "已领取的线索不能转移");
        }
        // 循环修改公海的线索的线索组为新线索组
        for (String leadId : po.getLeadIdList()){
            TXnLeadTeamDTO teamDTO = leadTeamMapper.selectById( po.getLeadTeamId());
            if (Objects.isNull(teamDTO)){
                leadMapper.updateBatchForIdList(leadId, Constant.DEFAULT_TEAM_NAME);
            }else {
                leadMapper.updateBatchForIdList(leadId, teamDTO.getTeamName());
            }

        }
        return new ReturnT(200,"操作成功");
    }

    /**
     * 后台线索管理：删除线索
     *  校验:线索是已领取（在私海线索中的）不允许删除
     *  逻辑：
     *      1通过线索ID查询公海线索数据，删除公海线索
     *      2，赋值回收站线索实体，然后新增一条回收站线索数据
     * @param idList
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public ReturnT deleteLeadForAdmin(List<String> idList) {
        Boolean flag =false;
        for (String leadId : idList){
            if (leadId.contains(EntityHelper.SiHaiXianSuo+"")){
                flag = true;
            }
        }
        if (flag){
            return new ReturnT(400, "已领取的线索不能删除");
        }
        for (String leadId : idList){
            TGonghaixiansuoDTO dto = gonghaixiansuoMapper.selectById(leadId);
            // 公海删除线索
            gonghaixiansuoMapper.deleteById(leadId);
            //xnLead做回收站表，回收站新增一条删除的数据
            TXnLeadDTO leadDTO = new TXnLeadDTO();
            BeanUtils.copyProperties(dto, leadDTO);
            ID id= ID.newId(EntityHelper.XnLead);
            leadDTO.setLeadId(String.valueOf(id));
            leadDTO.setDelYn(Constant.INT_1);
            if (StringUtils.isNotBlank(dto.getZhongyaochengdu())){
                leadDTO.setZhongyaochengdu(HowImportantEnum.getByValue(dto.getZhongyaochengdu()).getKey());
            }
            leadMapper.insert(leadDTO);
        }
        return new ReturnT(200,"操作成功"+idList.size()+"条");
    }

    @Override
    public IPage<XnLeadVO> selectLeadFallbackForAdmin(QueryLeadAdminPO po) {
        String tenantCode = UserContextHolder.getTenant();
        Page<TXnLeadDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        IPage<XnLeadVO> dtoList = leadMapper.selectFallbackPageList(page, po, Constant.INT_1, tenantCode);
        return dtoList;
    }

    /**
     * 后台线索回收站：还原线索
     *  逻辑：
     *      1，通过线索ID查询回收站线索数据，删除回收站线索
     *      2，赋值公海线索实体，然后新增一条公海线索数据
     * @param idList
     * @return
     */
    @Override
    public ReturnT resetLeadForAdmin(List<String> idList) {
        // 循环id查询线索的线索组ID
        for (String id :idList) {
            TXnLeadDTO dto = leadMapper.selectById(id);
            // 不存在：修改该线索的线索组ID为全公司线索组
            QueryWrapper<TXnLeadTeamDTO> wrapper = new QueryWrapper<>();
            wrapper.eq("TEAM_NAME", dto.getLeadTeam());
            TXnLeadTeamDTO teamDTO = leadTeamMapper.selectOne(wrapper);
            if (Objects.isNull(teamDTO)){
                dto.setLeadTeam(Constant.DEFAULT_TEAM_NAME);
            }
            leadMapper.deleteById(id);
            // 新增一条公海线索数据
            TGonghaixiansuoDTO gonghaixiansuoDTO = new TGonghaixiansuoDTO();
            BeanUtils.copyProperties(dto, gonghaixiansuoDTO);
            ID leadId= ID.newId(EntityHelper.GongHaiXianSuo);
            gonghaixiansuoDTO.setGonghaixiansuoId(String.valueOf(leadId));
            if (StringUtils.isNotBlank(dto.getZhongyaochengdu())){
                gonghaixiansuoDTO.setZhongyaochengdu(HowImportantEnum.getByKey(dto.getZhongyaochengdu()).getValue());
            }
            gonghaixiansuoMapper.insert(gonghaixiansuoDTO);
        }
        return ReturnT.SUCCESS;
    }

    /*************************************************************** 前台开始 ***************************************************************/

    @Override
    public IPage<XnLeadVO> selectLeadForHighSea(QueryLeadHighSeaPO po) {

        int rows = (int) po.getPageSize();
        int page = (int) po.getPageNum();
        ID currentUser = UserContextHolder.getUser();
        String tenantCode = UserContextHolder.getTenant();
        TUserDTO userDTO = userMapper.selectById(currentUser.toString());
        // 查询当前登录人对应组织ID及该组织下属组织ID集合
        List<String> deptArray = new ArrayList<>();
        deptArray.add(userDTO.getDeptId());
        getDeptList(deptArray, userDTO.getDeptId());
        System.out.println("部门ID集合------>"+ JSON.toJSON(deptArray));
        List<XnLeadVO> dtoList = new ArrayList<>();
        List<XnLeadVO> dtoList1 = leadMapper.selectHighSeaPageList(po, deptArray, Constant.INT_0, tenantCode);
        List<XnLeadVO> dtoList2 = leadMapper.selectCommonHighSeaPageList(po, deptArray, Constant.INT_0, tenantCode);
        dtoList.addAll(dtoList1);
        dtoList.addAll(dtoList2);
        // 数据去重
        dtoList = dtoList.stream().distinct().collect(Collectors.toList());
        // 对list集合进行分页处理
        int total=dtoList.size();
        dtoList=dtoList.subList(rows*(page-1), ((rows*page)>total?total:(rows*page)));
        IPage<XnLeadVO> pageList = new Page<>();
        pageList.setRecords(dtoList);
        pageList.setTotal(dtoList.size());
        return pageList;
    }

    /**
     * 递归查询：根据组织ID查询下级组织的ID集合，依次循环查询所有第一级下组织的子组织ID列表
     * @param deptAll
     * @param parentId
     */
    public void getDeptList(List<String> deptAll, String parentId){
        List<String> deptList = departmentMapper.selectDeptId(parentId);
        if (!deptList.isEmpty()){
            for (String deptId : deptList){
                deptAll.add(deptId);
                getDeptList(deptAll, deptId);
            }
        }
    }


    /**
     * 公海线索删除
     * 校验：当前操作人是该线索对应线索组的负责人才能删除
     * 逻辑：
     *  1，根据ID删除公海线索
     *  2，赋值回收站线索实体，新增一条回收站线索数据
     * @param id
     * @return
     */
    @Override
    public ReturnT deleteLeadForHighSea(String id) {
        ID currentUser = UserContextHolder.getUser();
        String headBy = leadMapper.selectHeadBy(id);
        if (StringUtils.isBlank(headBy)){
            return new ReturnT(400,"公海线索对应的线索组负责人不能为空");
        }
        if (!headBy.equals(currentUser.toString())) return new ReturnT(400,"不是该线索对应线索组负责人，不能删除");

        TGonghaixiansuoDTO dto = gonghaixiansuoMapper.selectById(id);
        // 公海删除线索
        gonghaixiansuoMapper.deleteById(id);
        // 赋值回收站线索实体，新增一条回收站线索数据
        TXnLeadDTO leadDTO = new TXnLeadDTO();
        BeanUtils.copyProperties(dto, leadDTO);
        ID leadId= ID.newId(EntityHelper.XnLead);
        leadDTO.setLeadId(String.valueOf(leadId));
        leadDTO.setDelYn(Constant.INT_1);
        if (StringUtils.isNotBlank(dto.getZhongyaochengdu())){
            leadDTO.setZhongyaochengdu(HowImportantEnum.getByValue(dto.getZhongyaochengdu()).getKey());
        }
        int i = leadMapper.insert(leadDTO);
        return i>0? new ReturnT(200,"操作成功"):new ReturnT(400, "操作失败");
    }

    /**
     * 公海线索分派
     * 校验：当前操作人是该线索对应线索组的负责人才能分派
     * 逻辑：
     *  1，根据ID删除公海线索
     *  2，赋值私海线索实体，新增一条私海线索数据
     * @param po
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public ReturnT assignLeadForHighSea(AssignLeadPO po) {
        ID currentUser = UserContextHolder.getUser();
        List<String> ids = po.getIds();
        for (String id : ids){
            TGonghaixiansuoDTO dto = gonghaixiansuoMapper.selectById(id);
            String headBy = leadMapper.selectHeadBy(id);
            if (StringUtils.isBlank(headBy)){
                return new ReturnT(400,"公海线索:"+dto.getLeadName()+"对应的线索组负责人为空");
            }
            if (!headBy.contains(currentUser.toString())) return new ReturnT(400,"【"+dto.getLeadName()+"】对应线索组负责人不是当前操作人，不能操作指派");
            // 限制数量规则校验领取数量是否已达到上限
            if (checkCountRule(po.getTo(), ids.size())){
                return new ReturnT(400, "领取人已达到线索领取数量上限，不能操作");
            }

            // 公海删除线索
            log.info("删除的公海线索：{}", JSON.toJSON(dto));
            gonghaixiansuoMapper.deleteById(id);
            // 赋值私海线索实体，新增一条私海线索数据
            TSihaixiansuoDTO leadDTO = new TSihaixiansuoDTO();
            BeanUtils.copyProperties(dto, leadDTO);
            leadDTO.setReceiveStatus("已领取");
            leadDTO.setOwningUser(po.getTo());
            User u = Application.getUserStore().getUser(ID.valueOf(po.getTo()));
            leadDTO.setOwningDept(String.valueOf(u.getOwningDept().getIdentity()));
            leadDTO.setCreatedOn(dto.getCreatedOn());
            leadDTO.setModifiedOn(new Date());
            ID leadId= ID.newId(EntityHelper.SiHaiXianSuo);
            leadDTO.setSihaixiansuoId(String.valueOf(leadId));
            sihaixiansuoMapper.insert(leadDTO);
        }
        return new ReturnT("操作成功");
    }

    /**
     * 公海线索领取
     * 校验：领取规则校验
     * 逻辑：
     *  1，根据ID删除公海线索
     *  2，赋值私海线索实体，新增一条私海线索数据
     * @param ids
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
    public ReturnT receiveLeadForHighSea(List<String> ids) {
        ID currentUser = UserContextHolder.getUser();
        for (String id : ids){
            TGonghaixiansuoDTO dto = gonghaixiansuoMapper.selectById(id);
            // 领取次数规则校验领取次数是否已达到上限
            if (checkReceiveRule(currentUser.toString(), ids.size())){
                return new ReturnT(400, "领取人已达到领取次数上限，不能操作");
            }
            // 限制数量规则校验领取数量是否已达到上限
            if (checkCountRule(currentUser.toString(), ids.size())){
                return new ReturnT(400, "领取人已达到线索领取数量上限，不能操作");
            }
            // 再次领取规则校验
            if (checkAgainReceiveRule(dto.getZidongweiyibianhao(), currentUser.toString())){
                return new ReturnT(400, "未到再次领取时间，不能操作");
            }
            // 公海删除线索
            log.info("删除的公海线索：{}", JSON.toJSON(dto));
            gonghaixiansuoMapper.deleteById(id);
            // 赋值私海线索实体，新增一条私海线索数据
            TSihaixiansuoDTO leadDTO = new TSihaixiansuoDTO();
            BeanUtils.copyProperties(dto, leadDTO);
            leadDTO.setOwningUser(currentUser.toString());
            User u = Application.getUserStore().getUser(currentUser);
            leadDTO.setOwningDept(String.valueOf(u.getOwningDept().getIdentity()));
            leadDTO.setReceiveStatus("已领取");
            leadDTO.setCreatedOn(dto.getCreatedOn());
            leadDTO.setModifiedOn(new Date());
            ID leadId= ID.newId(EntityHelper.SiHaiXianSuo);
            leadDTO.setSihaixiansuoId(String.valueOf(leadId));
            int i = sihaixiansuoMapper.insert(leadDTO);
        }
        return new ReturnT("操作成功");
    }

    @Override
    public ReturnT addLeadForHighSea(AddXnLeadPO po) {
        TXnLeadDTO dto = new TXnLeadDTO();
        BeanUtils.copyProperties(po, dto);
        ID userId= ID.newId(EntityHelper.XnLead);
        dto.setLeadId(String.valueOf(userId));
        dto.setModifiedBy(po.getCreatedBy());
        dto.setLeadTeam(Constant.DEFAULT_LEAD_TEAM);
        dto.setQuickCode(dto.getLeadTeam());
        dto.setGenjinzhuangtai(Constant.DEFAULT_GENJINZHUNGTAI);
        int result = leadMapper.insert(dto);
        return result>0? new ReturnT(String.valueOf(userId)):new ReturnT(400, "操作失败");
    }

    @Override
    public IPage<XnLeadVO> selectLeadForPrivateSea(QueryLeadHighSeaPO po) {
        ID currentUser = UserContextHolder.getUser();
        String tenantCode = UserContextHolder.getTenant();
        Page<TXnLeadDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        // 查询登录人是领取人的线索数据集合
        IPage<XnLeadVO> dtoList = leadMapper.selectLeadForPrivateSea(page, po, currentUser.toString(), Constant.INT_0, tenantCode);
        return dtoList;
    }

    @Override
    public ReturnT addLeadForPrivateSea(AddXnLeadPO po) {
        ID currentUser = UserContextHolder.getUser();
        TXnLeadDTO dto = new TXnLeadDTO();
        BeanUtils.copyProperties(po, dto);
        if (po.getLeadId() == null){
            ID userId= ID.newId(EntityHelper.XnLead);
            dto.setLeadId(String.valueOf(userId));
            dto.setModifiedBy(po.getCreatedBy());
            dto.setLeadTeam(Constant.DEFAULT_LEAD_TEAM);
            dto.setReceiveStatus(Constant.INT_1.toString());
            dto.setReceiveBy(currentUser.toString());
            dto.setReceiveOn(new Date());
            dto.setQuickCode(dto.getLeadTeam());
            dto.setGenjinzhuangtai(Constant.DEFAULT_GENJINZHUNGTAI);
            int result = leadMapper.insert(dto);
            return result>0? new ReturnT(String.valueOf(userId)):new ReturnT(400, "操作失败");
        }else {
            int result = leadMapper.updateById(dto);
            return result>0? new ReturnT(dto.getLeadId()):new ReturnT(400, "操作失败");
        }
    }

    /**
     * 私海线索：强制收回也是放回公海
     * @return
     */
    @Override
    public ReturnT recycleLeadForPrivateSea(PutLeadPO po) {
        return checkLeadIsReferenced(po);
    }

    /**
     * 私海线索：放回公海线索
     * 逻辑：
     *  1，删除私海线索
     *  2，新增公海线索
     * @param po
     * @return
     */
    @Override
    public ReturnT putBackLeadForPrivateSea(PutLeadPO po) {
        return checkLeadIsReferenced(po);
    }

    /**
     * 逻辑：
     *  1.查询线索所在所有实体是否被引用
     *  2，被引用&没有分派人则提示被应用，请选择新所属人
     *  3，被引用&有分派人则修改私海线索数据的所属人为分派的指定人员
     *  4，未被引用则则删除私海线索，生成公海线索
     * @param po
     * @return
     */
    public ReturnT checkLeadIsReferenced(PutLeadPO po){
        String tenantCode = UserContextHolder.getTenant();
        // 校验手动放回或者强制收回的线索有没有被引用，有的话则需要指派新所属人
        List<TMetaFieldDTO>  fieldDTOList = metaFieldMapper.selectListByField(null, "sihaixiansuo", null);
        List<Object> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fieldDTOList)){
            for (TMetaFieldDTO fieldDTO : fieldDTOList ){
                String sql = String.format("select %s from %s where %s = ? and tenantCode = ?",
                        fieldDTO.getFieldName(), fieldDTO.getBelongEntity(), fieldDTO.getFieldName());
                Query query = Application.getQueryFactory().createQueryNoFilter(sql);
                Object[][] array = query
                        .setParameter(1, ID.valueOf(po.getId()))
                        .setParameter(2, tenantCode)
                        .array();
                // 数组转换为集合
                if (array != null){
                    for (int i = 0; i < array.length; i++) {
                        for (int j = 0; j < array[i].length; j++) {
                            list.add(array[i][j]);
                        }
                    }
                }
            }
        }
        // 线索被引用
        if (!CollectionUtils.isEmpty(list)){
            log.info("线索:{}被引用",po.getId());
            if (StringUtils.isBlank(po.getTo())){
                return new ReturnT(400, "数据被其他实体引用，请分派新所属人");
            }else {
                TSihaixiansuoDTO dto = sihaixiansuoMapper.selectById(po.getId());
                if(dto != null){
                    dto.setOwningUser(po.getTo());
                    dto.setModifiedOn(new Date());
                    sihaixiansuoMapper.updateById(dto);
                }
            }
        }else {
            log.info("线索:{}未被引用",po.getId());
            // 未被引用，则删除私海线索，生成公海线索
            putBackLeadForPrivateSea(po.getId());
        }
        return new ReturnT(200 ,"操作成功");
    }

    /**
     * 私海线索数据放回公海
     * 前提：
     *  该私海线索数据没有被其他实体引用
     * @param id
     * @return
     */
    public ReturnT putBackLeadForPrivateSea(String id) {
        // 私海删除线索
        TSihaixiansuoDTO dto = sihaixiansuoMapper.selectById(id);
        sihaixiansuoMapper.deleteById(id);
        // 赋值私海线索实体，新增一条私海线索数据
        TGonghaixiansuoDTO leadDTO = new TGonghaixiansuoDTO();
        BeanUtils.copyProperties(dto, leadDTO);
        leadDTO.setOwningUser(UserService.ADMIN_USER.toString());
        leadDTO.setReceiveStatus("未领取");
        leadDTO.setCreatedOn(new Date());
        leadDTO.setModifiedOn(new Date());
        ID leadId= ID.newId(EntityHelper.GongHaiXianSuo);
        leadDTO.setGonghaixiansuoId(String.valueOf(leadId));
        int result = gonghaixiansuoMapper.insert(leadDTO);
        return result>0? new ReturnT(200,"操作成功"):new ReturnT(400, "操作失败");
    }

    /********************************* 规则校验相关 *******************************/

    /**
     * 限制数量规则校验
     * @param receiveBy
     * @return
     */
    private Boolean checkCountRule(String receiveBy, int size){
        TXnLimitRuleDTO ruleDTO = selectLimitRule(receiveBy, Constant.COUNT_RULE);
        // 角色没有配置限制规则的，不加数量限制
        if(Objects.isNull(ruleDTO)) return false;
        // 查看领取人已领取的线索数量
        QueryWrapper<TSihaixiansuoDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("OWNING_USER", receiveBy);
        Integer count = sihaixiansuoMapper.selectCount(wrapper);
        count = count + size;
        // 已分派数 == 限制数量 || 已分派数 > 限制数量
        if (count.equals(ruleDTO.getValue()) || count > ruleDTO.getValue()){
            return true;
        }
        return false;
    }

    /**
     * 领取规则校验
     * @param receiveBy
     * @return
     */
    private Boolean checkReceiveRule(String receiveBy, int size) {
        TXnLimitRuleDTO ruleDTO = selectLimitRule(null, Constant.RECEIVE_RULE);
        // 角色没有领取规则的，不加领取次数限制
        if(Objects.isNull(ruleDTO)) return false;
        // 查看领取人已领取的线索次数
        QueryWrapper<TXnLeadRecordDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("receive_by", receiveBy);
        if (ruleDTO.getLabel().equals(Constant.WEEK)){
            wrapper.between("receive_on", DateUtil.lastWeek(), new Date());
        }else {
            wrapper.between("receive_on", DateUtil.lastMonth(), new Date());
        }
        Integer count = recordMapper.selectCount(wrapper);
        count = count + size;
        // 领取的次数 == 规则对应的次数 || 领取的次数 > 规则对应的次数 提示领取次数已达上限
        if (count.equals(ruleDTO.getValue()) || count > ruleDTO.getValue()){
            return true;
        }
        return false;
    }

    /**
     * 再次领取规则校验
     * @param receiveBy
     * @return
     */
    private Boolean checkAgainReceiveRule(String code, String receiveBy) {
        TXnLimitRuleDTO ruleDTO = selectLimitRule(null, Constant.AGAIN_RULE);
        // 1，查询领取人对该线索的领取记录
        QueryWrapper<TXnLeadRecordDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("lead_id", code);
        wrapper.eq("receive_by", receiveBy);
        TXnLeadRecordDTO dto = recordMapper.selectOne(wrapper);
        // 2.1，线索记录表中存在
        if (Objects.nonNull(dto)){
            // 3，计算时间是否满足再次领取规则
            long hours = DateUtil.between(dto.getReceiveOn(), new Date(), DateUnit.HOUR);
            // 4，线索领取人是当前领取人 && 再次领取时间已满足
            if (Objects.isNull(ruleDTO)){
                dto.setReceiveOn(new Date());
                recordMapper.updateById(dto);
                return false;
            }else {
                if (hours > ruleDTO.getValue() * 24){
                    dto.setReceiveOn(new Date());
                    recordMapper.updateById(dto);
                    return false;
                }
            }
        }else {
            // 2.2，新增领取记录
            TXnLeadRecordDTO dto1 = new TXnLeadRecordDTO();
            dto1.setLeadId(code);
            dto1.setReceiveBy(receiveBy);
            dto1.setReceiveOn(new Date());
            recordMapper.insert(dto1);
            return false;
        }
        return true;
    }

    /**
     * 限制规则查询
     * @param userId
     * @param ruleCode
     * @return
     */
    private TXnLimitRuleDTO selectLimitRule(String userId, String ruleCode){
        QueryWrapper<TXnLimitRuleDTO> wrapper = new QueryWrapper<>();
        wrapper.eq("entity", Constant.LEAD_ENTITY);
        wrapper.eq("rule_code", ruleCode);
        wrapper.eq("is_disable", Constant.INT_0);
        if (userId != null){
            TUserDTO dto = userMapper.selectById(userId);
            wrapper.eq("label", dto.getRoleId());
        }
        TXnLimitRuleDTO ruleDTO = ruleMapper.selectOne(wrapper);
        return ruleDTO;
    }

    /**
     * 保存导入的线索数据
     * @param excelList
     * @param tenantCode
     * @return
     */
    @Override
    public Integer saveImportLead(List<ImportLeadPO> excelList, String tenantCode) throws Exception{
        int count=0;
        for (ImportLeadPO userExcel : excelList) {
            TGonghaixiansuoDTO dto = new TGonghaixiansuoDTO();
            BeanUtils.copyProperties(userExcel, dto);
            ID id= ID.newId(EntityHelper.GongHaiXianSuo);
            dto.setGonghaixiansuoId(String.valueOf(id));
            dto.setCreatedBy(String.valueOf(UserService.ADMIN_USER));
            dto.setModifiedBy(String.valueOf(UserService.ADMIN_USER));
            dto.setOwningUser(String.valueOf(UserService.ADMIN_USER));
            dto.setOwningDept(String.valueOf(DepartmentService.ROOT_DEPT));
            dto.setTenantCode(tenantCode);
            dto.setLeadTeam("无归属");
            dto.setReceiveStatus("未领取");
            dto.setZidongweiyibianhao(String.valueOf(id));
            Entity test = MetadataHelper.getEntity("gonghaixiansuo");
            Field classification = test.getField("area");
            ID itemId = ClassificationManager.instance.findItemByName(userExcel.getArea(), classification);
            if (itemId != null){
                dto.setArea(String.valueOf(itemId));
            }else {
                dto.setArea(null);
            }
            int i = gonghaixiansuoMapper.insert(dto);
            count = count+i;
        }
        return count;
    }

    /**
     * 线索管理：按照条件查询导出的线索数据
     * @param query
     * @return
     */
    @Override
    public List<XnLeadVO> selectExportLeadForAdmin(JSONObject query, Integer dr) {
        String tenantCode = UserContextHolder.getTenant();
        QueryLeadAdminPO po = new QueryLeadAdminPO();
        po.setPageNum(query.getInteger("pageNo"));
        // 1：选中的数据 2：当前页的数据 3：查询后的数据 4：全部数据
        if (dr == 1){
            po.setPageSize(query.getInteger("pageSize"));
            // 根据特殊字符"|"进行分割
            List<String> leadIds = Arrays.asList(query.getString("_selected").split("\\|"));
            po.setLeadIds(leadIds);
        }else if (dr == 2){
            po.setPageSize(query.getInteger("pageSize"));
            // 校验是否是条件查询
            boolean filterNonNull = Objects.nonNull(query.getString("param"));
            if(filterNonNull){
                po.setLeadName(query.getString("param"));
            }
        }else if (dr == 3){
            po.setPageSize(Constant.MAX_EXPORT);
            // 校验是否是条件查询
            boolean filterNonNull = Objects.nonNull(query.getString("param"));
            if(filterNonNull){
                po.setLeadName(query.getString("param"));
            }
        }else if (dr == 10){
            po.setPageSize(Constant.MAX_EXPORT);
        }
        Page<TXnLeadDTO> page = new Page<>(po.getPageNum(), po.getPageSize());
        List<XnLeadVO> dtoList = leadMapper.selectExportList(page, po, tenantCode);
        if (CollectionUtils.isNotEmpty(dtoList)){
            dtoList = paserDataToExport(dtoList);
        }
        return dtoList;
    }

    /**
     * 解析线索数据由id到汉字
     * 转换地区，线索来源，重要程度，线索状态，所属行业
     *
     * @param dtoList
     * @return
     */
    public List<XnLeadVO> paserDataToExport(List<XnLeadVO> dtoList){
        List<XnLeadVO> voList = new ArrayList<>();
        for (XnLeadVO leadVO : dtoList) {
            XnLeadVO vo = new XnLeadVO();
            BeanUtils.copyProperties(leadVO, vo);
            // 转换地区
            if (StringUtils.isNotBlank(leadVO.getArea())){
                ID areaId = ID.valueOf(leadVO.getArea());
                String itemId = ClassificationManager.instance.getName(areaId);
                vo.setArea(itemId);
            }
            // 线索来源
            if (StringUtils.isNotBlank(leadVO.getXiansuolaiyuan())){
                String fullName = ClassificationManager.instance.getFullName(ID.valueOf(leadVO.getXiansuolaiyuan()));
                vo.setXiansuolaiyuan(fullName);
            }
            // 重要程度
            if (StringUtils.isNotBlank(leadVO.getZhongyaochengdu())){
                DegreeImportantEnum i = DegreeImportantEnum.getByValue(leadVO.getZhongyaochengdu());
                vo.setZhongyaochengdu(i.getKey());
            }
            // 线索状态
            if (StringUtils.isNotBlank(leadVO.getGenjinzhuangtai())){
                LeadStatusEnum ls =  LeadStatusEnum.getByValue(leadVO.getGenjinzhuangtai());
                vo.setGenjinzhuangtai(ls.getKey());
            }
            // 所属行业
            if (StringUtils.isNotBlank(leadVO.getIndustry())){
                IndustryEnum in = IndustryEnum.getByValue(leadVO.getIndustry());
                vo.setIndustry(in.getKey());
            }
            voList.add(vo);
        }
        return voList;
    }

}
